﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

namespace Job.Core.Common
{
    /// <summary>
    /// 常用辅助操作类。
    /// </summary>
    public static class Utils
    {
        #region Enum

        /// <summary>
        /// 获取一个枚举类型的键值对字典。
        /// </summary>
        /// <param name="type">类型。</param>
        /// <returns>枚举键值对字典</returns>
        public static IDictionary<int, string> GetEnumDictionary(Type type)
        {
            if (!type.IsEnum)
                throw new ArgumentException("目标必需为枚举类型。");

            Dictionary<int, string> dic = new Dictionary<int, string>();

            string[] names = Enum.GetNames(type);
            int[] vals = (int[])Enum.GetValues(type);

            for (int i = 0; i < names.Length; i++)
            {
                dic.Add(vals[i], names[i]);
            }

            return dic;
        }

        #endregion

        #region Config

        /// <summary>
        /// 从配置文件中初始化配置对象。
        /// </summary>
        /// <param name="obj">要初始化的对象。</param>
        /// <param name="fileName">完整配置文件名。</param>
        public static void InitConfig(object obj, string fileName)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");

            if (fileName == null)
                throw new ArgumentNullException("fileName");

            if (!File.Exists(fileName))
                throw new FileNotFoundException("配置文件未找到。", fileName);

            var config = from c in XElement.Load(fileName).Elements() select c;
            Dictionary<string, string> dict = new Dictionary<string, string>();

            foreach (var el in config)
                dict.Add(el.Name.LocalName, el.Value);

            //使用反射初始化各属性。
            PropertyInfo[] infos = obj.GetType().GetProperties();

            foreach (PropertyInfo info in infos)
            {
                if (dict.ContainsKey(info.Name))
                {
                    if (info.CanWrite)
                        info.SetValue(obj, Convert.ChangeType(dict[info.Name], info.PropertyType), null);
                }
            }
        }

        /// <summary>
        /// 将配置对象更新至配置指定的配置文件。
        /// </summary>
        /// <param name="obj">对象实例。</param>
        /// <param name="fileName">完整配置文件名。</param>
        public static void UpdateConfig(object obj, string fileName)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");

            if (fileName == null)
                throw new ArgumentNullException("fileName");

            Dictionary<string, string> dict = new Dictionary<string, string>();
            PropertyInfo[] infos = obj.GetType().GetProperties();
            foreach (PropertyInfo info in infos)
            {
                if (info.CanWrite)
                    dict.Add(info.Name, info.GetValue(obj, null).ToString());
            }

            new XElement("config",
                from keyValue in dict
                select new XElement(keyValue.Key, new XCData(keyValue.Value))).Save(fileName);
        }

        #endregion
        
    }
}
